﻿namespace FitnessTracker.Calculators
{
    using System;
    using System.Collections.Generic;
    using FitnessTracker.Packet;

    public static class HeartBeatIntervalCalculator
    {
        private static ushort lastHeartBeatNumberReceived;

        public static IEnumerable<ushort> CalculateHeartBeatInterval(
           byte currentHeartBeatNumber,
           IList<ushort> heartBeatTimeStamps)
        {
            var numberOfIntervalsToRecord = CalculateNumberOfMissedIntervalsToRecord(currentHeartBeatNumber);
            var heartBeatIntervals = new List<ushort>(numberOfIntervalsToRecord);

            for (var i = 0; i < numberOfIntervalsToRecord; i++)
            {
                if (heartBeatTimeStamps[i] < heartBeatTimeStamps[i + 1])
                {
                    heartBeatIntervals.Add(
                        (ushort)((heartBeatTimeStamps[i] + heartBeatTimeStamps[i + 1]) % ushort.MaxValue));
                }
                else
                {
                    heartBeatIntervals.Add((ushort)(heartBeatTimeStamps[i] - heartBeatTimeStamps[i + 1]));
                }
            }

            lastHeartBeatNumberReceived = currentHeartBeatNumber;
            return heartBeatIntervals;
        }

        private static byte GetNumberOfMissedHearBeats(byte currentHeartBeatNumber)
        {
            if (currentHeartBeatNumber == lastHeartBeatNumberReceived)
            {
                return 0;
            }

            if (currentHeartBeatNumber < lastHeartBeatNumberReceived)
            {
                return (byte)((lastHeartBeatNumberReceived + currentHeartBeatNumber) % 
                              HxMPacketValueRanges.NumberOfHeartBeatTimeStampsPerPacket);
            }

            return (byte)Math.Min(
                currentHeartBeatNumber - lastHeartBeatNumberReceived, 
                HxMPacketValueRanges.NumberOfHeartBeatTimeStampsPerPacket);
        }

        private static byte CalculateNumberOfMissedIntervalsToRecord(byte currentHeartBeatNumber)
        {
            var missedHeartBeatIntervals = GetNumberOfMissedHearBeats(currentHeartBeatNumber);
            byte numberOfIntervalsToRecord;

            // First if is the case of the first packet received. Need to subtract 1 since impossible to 
            // determine interval for the very last stamp
            if (missedHeartBeatIntervals == HxMPacketValueRanges.NumberOfHeartBeatTimeStampsPerPacket)
            {
                numberOfIntervalsToRecord = HxMPacketValueRanges.NumberOfHeartBeatTimeStampsPerPacket - 1;
            }
            else
            {
                numberOfIntervalsToRecord = missedHeartBeatIntervals;
            }

            return numberOfIntervalsToRecord;
        }
    }
}
